package com.dianganjiao.lib.xbanner;

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Build;

import androidx.annotation.NonNull;

import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import com.bumptech.glide.load.resource.bitmap.TransformationUtils;
import com.bumptech.glide.util.Util;

import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.Arrays;

/**
 * Copyright：贵州玄机科技有限公司
 * Created by wxl on 2020/7/21 13:19
 * Description：
 * Modify time：
 * Modified by：
 */
public class RoundCorners extends BitmapTransformation {
    private static final String ID = "com.bumptech.glide.load.resource.bitmap.RoundedCorners";
    private static final byte[] ID_BYTES = ID.getBytes(CHARSET);

    private Float[] radius = new Float[4];


    /**
     * @throws IllegalArgumentException if rounding radius is 0 or less.
     */
    public RoundCorners(float tl, float tr, float br, float bl) {
        this.radius[0] = tl;
        this.radius[1] = tr;
        this.radius[2] = br;
        this.radius[3] = bl;
    }

    @Override
    protected Bitmap transform(
            @NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
        return roundedCorners(pool, toTransform, radius);
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof RoundCorners) {
            RoundCorners other = (RoundCorners) o;
            return Arrays.equals(this.radius, other.radius);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Util.hashCode(ID.hashCode(),
                Util.hashCode(Arrays.hashCode(radius)));
    }

    @Override
    public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
        messageDigest.update(ID_BYTES);

        byte[] radiusData = ByteBuffer.allocate(4).putInt(Arrays.hashCode(radius)).array();
        messageDigest.update(radiusData);
    }



    /**
     * Creates a bitmap from a source bitmap and rounds the corners.
     *
     * <p>This method does <em>NOT</em> resize the given {@link Bitmap}, it only rounds it's corners.
     * To both resize and round the corners of an image, consider
     * {@link com.bumptech.glide.request.RequestOptions#transforms(Transformation[])} and/or
     * {@link com.bumptech.glide.load.MultiTransformation}.
     *
     * @param inBitmap the source bitmap to use as a basis for the created bitmap.
     * @param
     * @return a {@link Bitmap} similar to inBitmap but with rounded corners.
     * @throws IllegalArgumentException if roundingRadius, width or height is 0 or less.
     */
    public static Bitmap roundedCorners(
            @NonNull BitmapPool pool, @NonNull Bitmap inBitmap, Float[] radius ) {


        // Alpha is required for this transformation.
        Bitmap.Config safeConfig = getAlphaSafeConfig(inBitmap);
        Bitmap toTransform = getAlphaSafeBitmap(pool, inBitmap);
        Bitmap result = pool.get(toTransform.getWidth(), toTransform.getHeight(), safeConfig);

        result.setHasAlpha(true);

        BitmapShader shader = new BitmapShader(toTransform, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setShader(shader);
        RectF rectF = new RectF(0, 0, result.getWidth(), result.getHeight());
        TransformationUtils.getBitmapDrawableLock().lock();
//        try {
//            Canvas canvas = new Canvas(result);
//            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
//            canvas.drawRoundRect(rect, roundingRadius, roundingRadius, paint);
//            canvas.setBitmap(null);
//        } finally {
//            TransformationUtils.getBitmapDrawableLock().unlock();
//        }
        Canvas canvas = new Canvas(result);
        // 左上
        float r = radius[0];
        canvas.save();
        canvas.clipRect(0, 0, canvas.getWidth() / 2, canvas.getHeight() / 2);
        canvas.drawRoundRect(rectF, r, r, paint);
        canvas.restore();
        // 右上
        r = radius[1];
        canvas.save();
        canvas.clipRect(canvas.getWidth() / 2, 0, canvas.getWidth(), canvas.getHeight() / 2);
        canvas.drawRoundRect(rectF, r, r, paint);
        canvas.restore();
        // 右下
        r = radius[2];
        canvas.save();
        canvas.clipRect(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getWidth(), canvas.getHeight());
        canvas.drawRoundRect(rectF, r, r, paint);
        canvas.restore();
        // 左下
        r = radius[3];
        canvas.save();
        canvas.clipRect(0, canvas.getHeight() / 2, canvas.getWidth() / 2, canvas.getHeight());
        canvas.drawRoundRect(rectF, r, r, paint);
        canvas.restore();

        if (!toTransform.equals(inBitmap)) {
            pool.put(toTransform);
        }


        return result;
    }

    private static Bitmap.Config getAlphaSafeConfig(@NonNull Bitmap inBitmap) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Avoid short circuiting the sdk check.
            if (Bitmap.Config.RGBA_F16.equals(inBitmap.getConfig())) { // NOPMD
                return Bitmap.Config.RGBA_F16;
            }
        }

        return Bitmap.Config.ARGB_8888;
    }


    private static Bitmap getAlphaSafeBitmap(
            @NonNull BitmapPool pool, @NonNull Bitmap maybeAlphaSafe) {
        Bitmap.Config safeConfig = getAlphaSafeConfig(maybeAlphaSafe);
        if (safeConfig.equals(maybeAlphaSafe.getConfig())) {
            return maybeAlphaSafe;
        }

        Bitmap argbBitmap =
                pool.get(maybeAlphaSafe.getWidth(), maybeAlphaSafe.getHeight(), safeConfig);
        new Canvas(argbBitmap).drawBitmap(maybeAlphaSafe, 0 /*left*/, 0 /*top*/, null /*paint*/);

        // We now own this Bitmap. It's our responsibility to replace it in the pool outside this method
        // when we're finished with it.
        return argbBitmap;
    }
}
